Nov 98 Getting Started
Volume Number: 14
Issue Number: 11
Column Tag: Getting Started
Color QuickDraw Basics
by Dave Mark and Dan Parks Sydow
How a Mac program handles color
Last month's column introduced black and white animation. Next month's column looks
at color animation. Before we make the transition from monochrome to color, we need
to gain an understanding of Color QuickDraw - the part of the Macintosh Toolbox that
allows a programmer to bring color into a program.
When creating a program, great effort can be spent in setting up data structures, or
developing algorithms, or performing some other behind-the-scenes chore. So often
times a programmer's hard work doesn't seem to really do much - a long programming
session may result in a lot of code being written, but very little of it displays anything
on screen. That's what makes working with color one of the most enjoyable parts of
programming. Not only do you get to see the results of your efforts, you get to see them
in brilliant, splendid color!
You'll have a little fun this month learning about programming in color - but we can't
let you have too much fun. With that in mind, this month's article also covers the
topics of multiple monitors and monitor pixel depth. Although you may only have one
monitor connected to your Mac, and although you may know the number of colors your
monitor is displaying, can you say the same for every one of the users of your
soon-to-be-written, best-selling, color Mac program? Here you'll see how your
program can easily account for the many possible monitor and color level
combinations on the systems of Mac users.
About Color QuickDraw
The original version of QuickDraw shipped with the very first Macs, and supported the
display of only black-and-white drawing on the built-in screen. To keep track of the
color of any one screen pixel required just a single bit (with the bit's two states
representing black and white). The original QuickDraw supported a pixel depth of 1 -
one bit dedicated to one pixel. Ever since the introduction of the Macintosh II, all Macs
have shipped with a new version of QuickDraw known as Color QuickDraw. Color
QuickDraw started as an 8-bit technology. Dedicating 8 bits to a pixel allowed for the
support of 256 colors, and gave this version of QuickDraw a pixel depth of 8. Color
QuickDraw then migrated to a 32-bit technology. This pixel depth of 32 could
supporting millions of colors.
It's been quite a while since Apple shipped a Mac that didn't support color, so in all
likelihood the user of your color program will be able to view it as you intended it to
be seen. Still, your program should verify that the host machine does in fact have a
version of Color QuickDraw. You'll do this for the sake of those few who are still using
monochrome Macs. If your program attempts to use Color QuickDraw Toolbox routines
on such a computer, it will crash that machine. Fortunately the Gestalt() Toolbox
function makes it easy to test for the presence of Color QuickDraw.
If you aren't familiar with Gestalt(), you should get acquainted with it. This routine is
a powerful tool that can be used to find out all sorts of things about the hardware and
software of the Mac that a program is currently running on. In general, if you want to
take advantage of a feature of the Macintosh that is not necessarily available on every
Mac, you'll want to call Gestalt() to make sure the feature is present. Here's the
prototype for Gestalt():
OSErr Gestalt( OSType selector, long *response );
Gestalt() takes two parameters. The first, selector, allows you to tell Gestalt() what
part of the hardware or software you are interested in. You can use Gestalt() to find
out how much RAM is on the current Mac, what version of the operating system is
installed, what processor is in the Mac, whether the machine supports Color
QuickDraw, and much, much more.
After executing, Gestalt() places the requested information in the second parameter,
response. The type of information in response depends on the selector used. There's an
Apple-defined selector constant for just about every imaginable Mac feature. Here
we'll look at just the gestaltQuickdrawVersion selector. You can check the Gestalt
Manager chapter of Inside Macintosh: Operating System Utilities, or peruse the
Gestalt.h universal interface header file, to learn more about Gestalt() and its various
selectors and responses.
To check for the presence of Color QuickDraw, begin by calling Gestalt() with a
selector of gestaltQuickdrawVersion:
long response;
OSErr err;
err = Gestalt( gestaltQuickdrawVersion, &response );
Now compare the returned value in response to one of the pertinent Apple-defined
response constants. For a selector of gestaltQuickdrawVersion there are five possible
values Gestalt() might return:
gestaltOriginalQD = 0x0000, /* original 1-bit QD */
gestalt8BitQD = 0x0100, /* 8-bit color QD */
gestalt32BitQD = 0x0200, /* 32-bit color QD */
gestalt32BitQD11 = 0x0201, /* 32-bit color QDv1.1 */
gestalt32BitQD12 = 0x0220, /* 32-bit color QDv1.2 */
gestalt32BitQD13 = 0x0230 /* 32-bit color QDv1.3 */
To check for a particular version of Color QuickDraw, test the response as such:
if ( response == gestalt32BitQD )
It's more likely that you're program will simply want to know if the user's machine
supports color - any color. To do that, see if the response is greater than the constant
representing the original, monochrome version of QuickDraw. Here's the test we'll be
using in this month's example:
if ( response > gestaltOriginalQD )
If the above test fails, exit the program or, better yet, call an error-handling routine
to alert the user of the incompatibility problem.
Monitors and Color Levels
If you connect a second monitor to your Macintosh, it may or may not have the same
pixel depth as the first monitor. That is, one monitor (or the graphics card controlling
the monitor) may be capable of displaying more colors than the other monitor. Even if
the two monitors are capable of displaying the same number of colors, at any given
time they may not be doing that - the user may have limited the pixel depth of a
monitor using the Monitors & Sound control panel. Because of this, the Mac needs a
means of being able to know the state of each monitor, or graphics device.
Color QuickDraw represents each graphics device attached to a Mac, whether a display
device or an offscreen color device (offscreen situations will be discussed in next
month's article), using a gDevice data structure. Toolbox routines like
GetDeviceList(), GetNextDevice(), and GetMainDevice() work with a gDevice data
structure. To obtain a handle to the first device in a gDevice list, call GetDeviceList():
GDHandle curDevice;

curDevice = GetDeviceList();
To find out which device is currently set to display the most colors, cycle through the
list of devices. To do that, call GetNextDevice() within a loop. Before getting the next
device from the gDevice list, check the pixel depth of the current device by calling the
application-defined routine GetDeviceDepth().
short curDepth;
while ( curDevice != NULL )
{
curDepth = GetDeviceDepth( curDevice );

curDevice = GetNextDevice( curDevice );
}
As you'll see in the code walk-though, there's a little bit more to it then what's shown
above. In particular, you'll need to see how the application-defined GetDeviceDepth()
is implemented. Also, when we encounter the device that has the greatest color depth,
we'll want to save that information in the body of the above loop.
The RGB Color Model
Color QuickDraw represents colors using the RGB model. RGB stands for red, green,
and blue - the three colors that combine to make up a single RGB color. The RGB model
is based on the RGBColor data structure:
struct RGBColor
{
unsigned short red;
unsigned short green;
unsigned short blue;
};
Each component of an RGBColor can take on a value from 0 to 65535. The lower the
value, the less intense the contribution of that one color to the overall, combined color.
For instance, if red is 65535 and blue and green are both 0, the resulting color is
bright red. As a second example, if the green component has a value of 0, and the red
and blue components each have a value of 65535, then the resulting color will be an
intense violet - a color rich in red and blue, but lacking any green. The extremes of
the color spectrum are black and white. If red, green, and blue are each 0, the
RGBColor represents black - the lack of any color in each component results in this
dimmest of colors. If all three components are each set to 65535, the RGBColor
represents white - the maximum intensity of each component creates this, the
brightest of colors. As an aside, "colors" is used loosely in the previous two sentences.
Black and white aren't truely colors: black is the absense of color, while white is the
mixture of all visible wavelengths (so white is the combination of all colors).
We'll work with the RGB model throughout this program. Be aware that Color
QuickDraw does support other color models, such as HSV (which is hue, saturation and
brightness) and CMY (which is cyan, magenta, yellow) and provides routines that
convert colors between each model.
To take advantage of the Color QuickDraw routines, you'll want to replace your use of
WindowRecords with CWindowRecords. CWindowRecords are similar to
WindowRecords, with a CGrafPort replacing the traditional GrafPort. Even with these
changes, you can pass a pointer to a CWindowRecord to all the routines that usually
take a WindowPtr. In this article's program, the only noticeable instance of working
with color windows is in the creation of a window, where a call to GetNewCWindow()
replaces the call we've used in the past - GetNewWindow().
ColorMondrian
This month's program, ColorMondrian, checks to see which monitor is capable of
displaying the most colors and then opens a window on that monitor. If the user's Mac
has only one monitor, then of course ColorMondrian knows to display the window on it.
After the window is resized to match the size of the monitor's screen, the program
draws randomly generated ovals, in randomly selected colors. ColorMondrian works
just fine on a system that has a grayscale monitor - in Color QuickDraw shades of gray
count as colors too! The shapes are continuously drawn until the user quits the
program. Figure 1 shows a part of the_ColorMondrian window as shapes are being
drawn to it.
Figure 1. The ColorMondrian window.
Creating the ColorMondrian Resources
To get started, move into your CodeWarrior development folder and create a folder
named ColorMondrian. Launch ResEdit and create a new resource file named
ColorMondrian.rsrc inside the ColorMondrian folder. Figure 2 shows the five types
of resources used by ColorMondrian - you'll notice that they're all types with which
you're familiar.
Figure 2. The MENU resources.
Figure 2 also shows the two particular MENU resources the program needs. Of course
your own real-world color application will have more MENU resources, including one
for the standard Edit menu and one for each application-defined menu.
ColorMondrian uses one ALRT and one DITL resource - they're shown in Figure 3. Both
are used to support the error-handling alert displayed by the program's DoError()
routine (a routine touched on in the ColorMondrian walk-through, and discussed at
length two articles ago in the Getting Started column on Apple Events).
Figure 3. The resources needed to implement error-handling.